package com.suray.wcs.service.websocket;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Maps;
import com.suray.basic.wcs.node.WCSNodeModule;
import com.suray.basic.wcs.node.bo.WCSNodeModuleBO;
import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.path.enums.NodeType;
import com.suray.basic.wcs.plc.core.Plc;
import com.suray.basic.wcs.plc.entity.PlcDeviceDB;
import com.suray.basic.wcs.plc.enums.PlcDeviceType;
import com.suray.basic.wcs.plc.pojo.*;
import com.suray.basic.wcs.plc.pojo.device.Scanner;
import com.suray.basic.wcs.plc.pojo.oper.lifter.ForkLifterOper;
import com.suray.basic.wcs.plc.pojo.oper.lifter.LifterOper;
import com.suray.basic.wcs.plc.pojo.oper.*;
import com.suray.basic.wcs.plc.pojo.oper.single.*;
import com.suray.basic.wcs.plc.service.IPlcDeviceDBService;
import com.suray.basic.wcs.plc.service.impl.PlcDeviceDBServiceImpl;
import com.suray.basic.wcs.utils.Coord;
import com.suray.basic.wcs.utils.LockNode;
import com.suray.commin.core.controller.ResponseData;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.rgv.RgvSMInterface;
import com.suray.wcs.res.enums.RgvType;
import com.suray.wcs.service.core.util.LockNodeManager;
import com.suray.wcs.service.enums.DeviceType;
import com.suray.wcs.service.enums.WebSocketType;
import com.suray.wcs.service.init.SystemInit;
import com.suray.wcs.service.init.device.DeviceManager;
import com.suray.wcs.service.plc.LifterEvent;
import com.suray.wcs.service.pojo.*;
import com.suray.wcs.service.system.entity.NodeDB;
import com.suray.wcs.service.system.entity.TaskDB;
import com.suray.wcs.service.system.service.impl.HoisterOperServiceImp;
import com.suray.wcs.service.system.service.impl.NodeDBServiceImpl;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * websocket服务
 *
 * @author rbj
 */
@ServerEndpoint(value = "/websocket/{sid}/{webSocketType}", encoders = {ServerEncoder.class})
@Component
public class WebSocketServer {
    private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    /**
     * 使用map对象，便于根据userId来获取对应的WebSocket
     */
    private static ConcurrentHashMap<String, WebSocketServer> webSocketList = new ConcurrentHashMap<>();
    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;
    /**
     * WebSocketServer 的唯一标识
     */
    private String sid;

    public String getWebSocketType() {
        return webSocketType;
    }

    public void setWebSocketType(String webSocketType) {
        this.webSocketType = webSocketType;
    }

    /**
     * 当前需要推送数据的Rgv
     */
    private Rgv rgv;

    /**
     * 当前webSocket的类型
     */
    private String webSocketType;

    public Integer getParam() {
        return param;
    }

    public void setParam(Integer param) {
        this.param = param;
    }

    /**
     * 前端给的参数（层或者是坐标编号）
     */
    private Integer param;
    /**
     * 提升机信息查询
     */
    private static PlcDeviceDBServiceImpl plcdevicedbServiceImpl = SpringContextHolder.getBean(PlcDeviceDBServiceImpl.class);
    private static HoisterOperServiceImp hoisterOperServiceImp = SpringContextHolder.getBean(HoisterOperServiceImp.class);
    private static final IPlcDeviceDBService plcDeviceDBService = SpringContextHolder.getBean(IPlcDeviceDBService.class);
    private static final NodeDBServiceImpl nodeDBService = SpringContextHolder.getBean(NodeDBServiceImpl.class);

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid, @PathParam("webSocketType") String webSocketType) {
        this.session = session;
        this.sid = sid;
        this.setWebSocketType(webSocketType);
        webSocketList.put(sid, this);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (webSocketType.equals(WebSocketType.CURRENT_NODE.getType())) {
            rgv = null;
        }
        webSocketList.remove(sid, this);
    }


    /**
     * 实现服务器主动推送
     *
     * @throws IOException
     * @throws EncodeException
     */
    public void sendMessage(Object data) throws IOException, EncodeException {
        this.session.getBasicRemote().sendObject(data);
    }

    @OnMessage
    public void onMessage(Integer param) throws IOException {
        this.param = param;
        if (webSocketType.equals(WebSocketType.CURRENT_NODE.getType())) {
            NodeDB nodeDB = nodeDBService.getById(param);
            Rgv curNodeRgv = getRgvByCoord(new Coord(nodeDB.getGridx(), nodeDB.getGridy(), nodeDB.getGridz()));
            if (curNodeRgv != null) {
                rgv = curNodeRgv;
            }
        }
    }


    /**
     * 群发自定义消息
     *
     * @throws EncodeException
     * @throws IOException
     */
    public static void sendInfo(Object data) throws Exception {
        for (String key : webSocketList.keySet()) {
            synchronized (key) {
                WebSocketServer webSocketServer = webSocketList.get(key);
                if (WebSocketType.NODE.getType().equals(webSocketServer.getWebSocketType())) {
                    webSocketServer.sendMessage(ResponseData.success(data));
                }
            }
        }
    }

    /**
     * 前端所选择的当前层的小车和工位
     */
    public static void sendCurrLayerInfo() {
        for (String key : webSocketList.keySet()) {
            synchronized (key) {
                WebSocketServer webSocketServer = webSocketList.get(key);
                if (WebSocketType.CURRENT_FLOOR.getType().equals(webSocketServer.getWebSocketType())) {
                    Integer floor = webSocketServer.getParam();
                    if (floor != null) {
                        try {
                            List<RgvInfoFloor> rgvInfoFloorList = SystemInit.getRgvInfoFloorList(floor);
                            List<Station> stationList = getChainsFloor(floor);
                            Map<String, List> map = Maps.newHashMap();
                            if(CollectionUtils.isNotEmpty(rgvInfoFloorList)) {
                                map.put("rgvList", rgvInfoFloorList);
                            }
                            if(CollectionUtils.isNotEmpty(stationList)) {
                                map.put("stationList", stationList);
                            }
                            map.put("nodeBOs", nodeDBService.getResourcesNodes(floor));
                            webSocketServer.sendMessage(ResponseData.success(map));
                        } catch (Exception e) {
                            log.error("获取当前层小车和工位信息失败！{}", e);
                        }
                    }

                }
            }
        }
    }

    /**
     * 向前端推送仓库监控界面小车列表数据
     */
    public static void sendRgvListInfo() throws IOException, EncodeException {
        for (String key : webSocketList.keySet()) {
            synchronized (key) {
                WebSocketServer webSocketServer = webSocketList.get(key);
                if (WebSocketType.RGV_LIST.getType().equals(webSocketServer.getWebSocketType())) {
                    List<RgvInfo> rgvInfoList = SystemInit.getRgvInfoList();
                    webSocketServer.sendMessage(ResponseData.success(rgvInfoList));
                }
            }
        }
    }

    /**
     * 向前端推送仓库监控界面提升机列表数据
     */
    public static void sendLifterListInfo() throws IOException, EncodeException {
        for (String key : webSocketList.keySet()) {
            synchronized (key) {
                WebSocketServer webSocketServer = webSocketList.get(key);
                if (WebSocketType.LIFTER_LIST.getType().equals(webSocketServer.getWebSocketType())) {
                    List<LifterInfo> hoistList = getHoistList();
                    webSocketServer.sendMessage(ResponseData.success(hoistList));
                }
            }
        }
    }

    /**
     * 当前节点对应的设备的信息
     */
    public static void sendCurrCoordInfo() {
        for (String key : webSocketList.keySet()) {
            synchronized (key) {
                try {
                    WebSocketServer webSocketServer = webSocketList.get(key);
                    if (WebSocketType.CURRENT_NODE.getType().equals(webSocketServer.getWebSocketType())) {
                        Integer nodeId = webSocketServer.getParam();
                        NodeDB nodeDB = nodeDBService.getById(nodeId);

                        if (nodeDB != null) {
                            List<Map<String, Object>> webSocketResult = new ArrayList();
                            Coord coord = new Coord(nodeDB.getGridx(), nodeDB.getGridy(), nodeDB.getGridz());
                            if (nodeDB.getGridType().equals(NodeType.L)) {
                                coord.setZ(1);
                            }
                            List<PlcDeviceDB> plcDevices = plcdevicedbServiceImpl.getPlcByLocation(coord);
                            plcDevices.forEach(plcDeviceDB -> {
                                Map<String, Object> plcDeviceMap = Maps.newHashMap();
                                plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                // 工位信息
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.CHAIN_STATION.getTypeNum())) {
                                    HandleChainStatus handleChainStatus = plcDeviceDBService.plcChainStationDeviceR(plcDeviceDB.getDeviceName());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleChainStatus);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                // 外形检测信息
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.SHAPE_DETECTION.getTypeNum())) {
                                    HandleShape handleShape = plcDeviceDBService.plcShapeDeviceR(plcDeviceDB.getDeviceName());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleShape);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                // 扫码信息
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.SCANNER.getTypeNum())) {
                                    ScannerHandleBean scannerHandleBean = plcDeviceDBService.readBarCode(plcDeviceDB.getDeviceName());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", scannerHandleBean);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                // 称重设备信息
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.WEIGHT.getTypeNum())) {
                                    HandleWeight handleWeight = plcDeviceDBService.plcWeightDeviceR(plcDeviceDB.getDeviceName());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleWeight);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                // 自动门设备信息
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.AUTOMATIC_DOOR.getTypeNum())) {
                                    HandleAutoDoor handleAutoDoor = plcDeviceDBService.plcAutoDoorDevice(plcDeviceDB.getDeviceName());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleAutoDoor);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                // 自动门2设备信息
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.SINGLE_AUTO_DOOR.getTypeNum())) {
                                    HandleAutoDoor2 handleAutoDoor2 = plcDeviceDBService.plcAutoDoorDevice2(plcDeviceDB.getDeviceName());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleAutoDoor2);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //自动升降机信息
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.AUTO_HOIST.getTypeNum())) {
                                    HandleAutoHoistOper handleAutoHoistOper = plcDeviceDBService.plcAutoHoistDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleAutoHoistOper);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //牙叉升降机信息
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.TOOTH_HOIST.getTypeNum())) {
                                    HandleToothHoistOper handleToothHoistOper = SystemInit.plcToothHoistDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleToothHoistOper);
                                    webSocketResult.add(plcDeviceMap);
                                }//拆叠盘机信息
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.FOLDING_MACHINE.getTypeNum())) {
                                    HandleFoldingMachineOper handleFoldingMachineOper = SystemInit.plcFoldingDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleFoldingMachineOper);
                                    webSocketResult.add(plcDeviceMap);
                                }

                                // 提升机设备信息
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.TAMAGAWA_LIFTER.getTypeNum()) ||
                                        plcDeviceDB.getDeviceType().equals(PlcDeviceType.PANASONIC_LIFT.getTypeNum()) ||
                                        plcDeviceDB.getDeviceType().equals(PlcDeviceType.SIEMENS_HOIST.getTypeNum()) ||
                                        plcDeviceDB.getDeviceType().equals(PlcDeviceType.AUTOMATIC_LIFTER.getTypeNum()) ||
                                        plcDeviceDB.getDeviceType().equals(PlcDeviceType.FORK_LIFTER.getTypeNum())

                                ) {
                                    plcDeviceMap.put("type", "2");
                                    HandHoist hoistSingle = getHoistSingle(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("data", hoistSingle);
                                    webSocketResult.add(plcDeviceMap);
                                }

                                //自动横移机
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.AUTO_TRAVERSING.getTypeNum())) {
                                    HandleAutoTraversingOper handleAutoTraversingOper = SystemInit.plcAutoTraversingDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleAutoTraversingOper);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //移裁机
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.TRANS_PLANTER.getTypeNum())) {
                                    HandleTransP handleTransP = plcDeviceDBService.plcTransPDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleTransP);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //单体输送线
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.MONOMER_CONVEYOR.getTypeNum())) {
                                    HandleMonomerConveyorOper handleMonomerConveyorOper = SystemInit.plcMonomerConveyorDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleMonomerConveyorOper);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //单体输送线 + 外形检测
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.SHAPE_CONVEYOR.getTypeNum())) {
                                    HandleShapeConveyor handleShapeConveyor = plcDeviceDBService.plcShapeConveyorDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleShapeConveyor);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //外形检测
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.SHAPE.getTypeNum())) {
                                    HandleShapeConveyor handleShapeConveyor = plcDeviceDBService.plcShapeConveyorDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleShapeConveyor);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //扫码
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.SCAN.getTypeNum())) {
                                    HandleScanOper handleScanOper = plcDeviceDBService.plcScanDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleScanOper);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //称重
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.SINGLE_WEIGHT.getTypeNum())) {
                                    HandleWeightOper handleWeightOper = plcDeviceDBService.plcWeightDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleWeightOper);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //提升机基础设备
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.LIFTER_BASE.getTypeNum())) {
                                    HandleLifterBase handleLifterBase = SystemInit.lifterBaseDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleLifterBase);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //提升机系统
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.LIFTER_SYSTEM.getTypeNum())) {
                                    HandleLifterSystem handleLifterSystem = plcDeviceDBService.lifterSystemDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleLifterSystem);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //提升机工位
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.LIFTER_STATION.getTypeNum())) {
                                    HandleLifterStation handleLifterStation = plcDeviceDBService.lifterStationDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleLifterStation);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //提升机左工位
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.LIFTER_LEFT_STATION.getTypeNum())) {
                                    HandleLifterStation handleLifterStation = plcDeviceDBService.lifterStationDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleLifterStation);
                                    webSocketResult.add(plcDeviceMap);
                                }
                                //提升机右工位
                                if (plcDeviceDB.getDeviceType().equals(PlcDeviceType.LIFTER_RIGHT_STATION.getTypeNum())) {
                                    HandleLifterStation handleLifterStation = plcDeviceDBService.lifterStationDevice(plcDeviceDB.getDeviceId());
                                    plcDeviceMap.put("type", plcDeviceDB.getDeviceType());
                                    plcDeviceMap.put("data", handleLifterStation);
                                    webSocketResult.add(plcDeviceMap);
                                }
                            });
                            devicePush(webSocketResult, coord);
                            if (webSocketServer.rgv != null) {
                                if (webSocketServer.rgv.checkRgvType(RgvType.RGV_SIX_POINT_ZERO)) {
                                    Rgv60InfoSingle rgvInfoSingle
                                            = SystemInit.Rgv60InfoSingle((Rgv60) webSocketServer.rgv);
                                    Map<String, Object> mapConnectionRgv = Maps.newHashMap();
                                    mapConnectionRgv.put("type", "rgv60");
                                    mapConnectionRgv.put("data", rgvInfoSingle);
                                    webSocketResult.add(mapConnectionRgv);
                                } else if (webSocketServer.rgv.checkRgvType(RgvType.RGV_ROLLER)){
                                    Rgv60InfoSingle rgvInfoSingle
                                            = SystemInit.Rgv60InfoSingle((RgvRoller) webSocketServer.rgv);
                                    Map<String, Object> mapConnectionRgv = Maps.newHashMap();
                                    mapConnectionRgv.put("type", "rgvRoller");
                                    mapConnectionRgv.put("data", rgvInfoSingle);
                                    webSocketResult.add(mapConnectionRgv);
                                } else if (webSocketServer.rgv.checkRgvType(RgvType.RGV_SON_MOTHER)){
                                    RgvSMInfoSingle rgvInfoSingle
                                            = SystemInit.RgvSMInfoSingle((RgvSM) webSocketServer.rgv);
                                    Map<String, Object> mapConnectionRgv = Maps.newHashMap();
                                    mapConnectionRgv.put("type", "rgvSM");
                                    mapConnectionRgv.put("data", rgvInfoSingle);
                                    webSocketResult.add(mapConnectionRgv);
                                } else if (webSocketServer.rgv.checkRgvType(RgvType.RGV_FORK)) {
                                    RgvForkInfoSingle rgvInfoSingle
                                            = SystemInit.RgvForkInfoSingle((RgvFork) webSocketServer.rgv);
                                    Map<String, Object> mapConnectionRgv = Maps.newHashMap();
                                    mapConnectionRgv.put("type", "rgvFork");
                                    mapConnectionRgv.put("data", rgvInfoSingle);
                                    webSocketResult.add(mapConnectionRgv);
                                } else {
                                    RgvInfoSingle rgvInfoSingle = SystemInit.getRgvInfoSingle(webSocketServer.rgv);
                                    Map<String, Object> mapConnectionRgv = Maps.newHashMap();
                                    mapConnectionRgv.put("type", "rgv");
                                    mapConnectionRgv.put("data", rgvInfoSingle);
                                    webSocketResult.add(mapConnectionRgv);
                                }
                            }

                            Map<String, Object> mapNode = Maps.newHashMap();
                            mapNode.put("type", "0");
                            Node node = new Node(nodeDB.getGridx(), nodeDB.getGridy(), nodeDB.getGridz());
                            WCSNodeModuleBO wcsNodeModuleBO = WCSNodeModule.wcsNodeModuleMapCache.get(node.toString());
                            NodeInfo nodeInfo = new NodeInfo();
                            BeanUtils.copyProperties(nodeDB, nodeInfo);
                            if (wcsNodeModuleBO != null) {
                                nodeInfo.setLockTime(wcsNodeModuleBO.getMaxLockTimeWCSNodeModuleRouteBO().getLockTime());
                                nodeInfo.setPassTime(wcsNodeModuleBO.getMaxLockTimeWCSNodeModuleRouteBO().getPassTime());
                                nodeInfo.setCurrentPassTime(wcsNodeModuleBO.getMaxLockTimeWCSNodeModuleRouteBO().getCurrentPassTime());
                            }
                            Set<LockNode> lockedNodes = LockNodeManager.getLockedNodes();
                            for (LockNode lockNode : lockedNodes) {
                                if (lockNode.getX() == node.getX() && lockNode.getY() == node.getY() && lockNode.getZ() == node.getZ()) {
                                    nodeInfo.setUnLockTime(lockNode.getUnLockTime());
                                }
                            }
                            Coord c = new Coord(nodeDB.getGridx(), nodeDB.getGridy(), nodeDB.getGridz());
                            Set<Coord> coordSet = new HashSet<>();
                            coordSet.add(c);
                            Object obj = LockNodeManager.isLocked(coordSet);
                            String lockBy;
                            nodeInfo.setLocked(obj != null ? true : false);
                            if (obj == null) {
                                lockBy = "暂无";
                            } else if (obj instanceof Rgv) {
                                lockBy = ((Rgv) obj).getRgvName();
                            } else if (obj instanceof TaskDB) {
                                lockBy = ((TaskDB) obj).getTaskId().toString();
                            } else if (obj instanceof RgvSMInterface) {
                                lockBy = ((RgvSMInterface) obj).getSeries() + "子车";
                            } else {
                                lockBy = obj.toString();
                            }
                            nodeInfo.setLockedBy(lockBy);
                            obj = LockNodeManager.isDeviceLocked(coordSet);
                            nodeInfo.setDeviceLocked(obj != null ? true : false);
                            if (obj == null) {
                                lockBy = "暂无";
                            } else if (obj instanceof Rgv) {
                                lockBy = ((Rgv) obj).getRgvName();
                            } else if (obj instanceof TaskDB) {
                                lockBy = ((TaskDB) obj).getTaskId().toString();
                            } else {
                                lockBy = obj.toString();
                            }
                            nodeInfo.setDeviceLockedBy(lockBy);
                            if (nodeDB.getTag()!=null) {
                                nodeInfo.setTag(nodeDB.getTag());
                            }
                            nodeDBService.changeFBGIntToString(nodeDB);
                            nodeInfo.setForbidRgvs(nodeDB.getForbidRgvs());
                            mapNode.put("data", nodeInfo);
                            webSocketResult.add(mapNode);
                            webSocketServer.sendMessage(ResponseData.success(webSocketResult));
                        }
                    }
                } catch (Exception e) {
                    log.error("获取当前节点信息失败！{}", e.getMessage(), e);
                }
            }
        }
    }

    /**
     * 根据坐标点推送外部设备
     * @param webSocketResult
     * @param coord
     */
    private static void devicePush(List<Map<String, Object>> webSocketResult, Coord coord) {
        devicePush(webSocketResult, DeviceType.MACHINE_HAND.toString(), DeviceManager.getByRobotCoord(coord));
        devicePush(webSocketResult, DeviceType.SCANNER.toString(), DeviceManager.getByScanCoord(coord));
    }

    private static void devicePush(List<Map<String, Object>> webSocketResult, String str, Object obj) {
        if (obj != null) {
            Map<String, Object> deviceMap = Maps.newHashMap();
            if(str.equals("SM")){
                ScannerEquipment scannerEquipment=new ScannerEquipment();
                Scanner scanner=((Scanner) obj);
                scannerEquipment.setScanName(scanner.getScanName());
                scannerEquipment.setLocation(scanner.getLocation().toString());
                scannerEquipment.setDeviceNo(scanner.getDeviceNo());
                scannerEquipment.setBarcode(scanner.getBarcode());
                scannerEquipment.setEnable(scanner.isEnable());
                deviceMap.put("data", scannerEquipment);
            }else{
                deviceMap.put("data", obj);
            }
            deviceMap.put("type", str);
            webSocketResult.add(deviceMap);
        }
    }

    /**
     * 获取当前位置的小车
     *
     * @param coord
     * @return
     */
    private static Rgv getRgvByCoord(Coord coord) {
        Stream<Rgv> rgvStream = SystemInit.RGVS.stream().filter(rgv -> rgv.getRgvDB().getLocationNode().equals(coord));
        List<Rgv> collect = rgvStream.collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(collect)) {
            return collect.get(0);
        }
        return null;
    }


    /**
     * 获取提升机列表
     *
     * @return
     */
    public static List<LifterInfo> getHoistList() {
        List<LifterInfo> lifterInfos = new ArrayList<>();
        List<HandHoist> handHoistList = getHandHoists();
        if (CollectionUtils.isNotEmpty(handHoistList)) {
            for (HandHoist handHoist : handHoistList) {
                LifterInfo lifterInfo = new LifterInfo();
                BeanUtils.copyProperties(handHoist, lifterInfo);
                lifterInfos.add(lifterInfo);
            }
        }
        return lifterInfos;
    }

    /**
     * @return hoists
     * @Description:查询处理并返回提升机信息
     */
    public static HandHoist getHoistSingle(int hoistNo) {
        List<HandHoist> handHoistList = getHandHoists();
        if (CollectionUtils.isNotEmpty(handHoistList)) {
            for (HandHoist handHoist : handHoistList) {
                if (hoistNo == Integer.parseInt(handHoist.getHoistNo())) {
                    return handHoist;
                }
            }
        }
        return null;
    }

    /**
     * @return List<HandHoist>
     * @Description:查询处理并返回提升机信息
     */
    public static List<HandHoist> getHandHoists() {
        List<HandHoist> hoists = new ArrayList<>();
        List<PlcDeviceDB> plcDeviceDBS = plcdevicedbServiceImpl.queryLiftList();
        LifterOper lifterOper;
        ForkLifterOper forkLifterOper;
        if (plcDeviceDBS != null && plcDeviceDBS.size() > 0) {
            for (PlcDeviceDB plcdevicedb : plcDeviceDBS) {
                if (plcdevicedb.getDeviceType() != PlcDeviceType.FORK_LIFTER.getTypeNum()) {
                    HandHoist handHoist = new HandHoist();
                    handHoist.setHoistNo(Integer.toString(plcdevicedb.getDeviceId()));
                    handHoist.setHoistName(plcdevicedb.getDeviceName());
                    lifterOper = (LifterOper) Plc.deviceLifterCoordMap.get(Node.parseGrid(plcdevicedbServiceImpl.getById(plcdevicedb.getDeviceId()).getPlcLockLocation()));
                    if (lifterOper == null) {
                        handHoist.setDeviceLocation(
                                //前端需要格式为x,y,z的坐标
                                plcdevicedb.getDeviceLocation().substring(plcdevicedb.getDeviceLocation().indexOf("(") + 1,
                                        plcdevicedb.getDeviceLocation().indexOf(")")));
                        handHoist.setReadyState("离线");
                    } else {
                        handHoist = hoisterOperServiceImp.getHoistInfo(lifterOper);
                        handHoist.setHoistType(String.valueOf(plcdevicedb.getDeviceType()));
                        handHoist.setDeviceLocation(
                                //前端需要格式为x,y,z的坐标
                                plcdevicedb.getDeviceLocation().substring(plcdevicedb.getDeviceLocation().indexOf("(") + 1,
                                        plcdevicedb.getDeviceLocation().indexOf(")")));
                        handHoist.setHoistName(plcdevicedb.getDeviceName());
                        handHoist.setHoistNo(Integer.toString(plcdevicedb.getDeviceId()));
                        handHoist.setLiftWord(LifterEvent.liftWord.get(plcdevicedb.getDeviceLocation()) == null ? "完成编号读取完成" : String.valueOf(LifterEvent.liftWord.get(plcdevicedb.getDeviceLocation())));
                    }
                    if (handHoist != null) {
                        hoists.add(handHoist);
                    }
                } else {
                    HandHoist handHoist = new HandHoist();
                    handHoist.setHoistNo(Integer.toString(plcdevicedb.getDeviceId()));
                    handHoist.setHoistName(plcdevicedb.getDeviceName());
                    forkLifterOper = (ForkLifterOper) Plc.deviceLifterCoordMap.get(Node.parseGrid(plcdevicedbServiceImpl.getById(plcdevicedb.getDeviceId()).getPlcLockLocation()));
                    if (forkLifterOper == null) {
                        handHoist.setDeviceLocation(
                                //前端需要格式为x,y,z的坐标
                                plcdevicedb.getDeviceLocation().substring(plcdevicedb.getDeviceLocation().indexOf("(") + 1,
                                        plcdevicedb.getDeviceLocation().indexOf(")")));
                        handHoist.setReadyState("离线");
                    } else {
                        handHoist = hoisterOperServiceImp.getForkHoisterInfo(forkLifterOper);
                        handHoist.setHoistType(String.valueOf(plcdevicedb.getDeviceType()));
                        handHoist.setDeviceLocation(
                                //前端需要格式为x,y,z的坐标
                                plcdevicedb.getDeviceLocation().substring(plcdevicedb.getDeviceLocation().indexOf("(") + 1,
                                        plcdevicedb.getDeviceLocation().indexOf(")")));
                        handHoist.setHoistName(plcdevicedb.getDeviceName());
                        handHoist.setHoistNo(Integer.toString(plcdevicedb.getDeviceId()));
                    }
                    if (handHoist != null) {
                        hoists.add(handHoist);
                    }

                }

            }
        }
        return hoists;
    }

    /**
     * @return hoists
     * @Description:查询处理并返回提升机信息
     */
    public static List<Station> getChainsFloor(Integer floor) {
        if (floor == null) {
            return null;
        }
        List<Station> stationList = getChainStation();
        if (CollectionUtils.isNotEmpty(stationList)) {
            Iterator iterator = stationList.iterator();
            while (iterator.hasNext()) {
                if (((Station) iterator.next()).getDeviceLocation().getZ() != floor) {
                    iterator.remove();
                }
            }
        }
        return stationList;
    }

    public static List<Station> getChainStation() {
        List<Station> stations = new ArrayList<>();
        QueryWrapper<PlcDeviceDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(PlcDeviceDB::getDeviceType, PlcDeviceType.CHAIN_STATION.getTypeNum())
                .or()
                .eq(PlcDeviceDB::getDeviceType, PlcDeviceType.MONOMER_CONVEYOR.getTypeNum())
                .or()
                .eq(PlcDeviceDB::getDeviceType, PlcDeviceType.TOOTH_HOIST.getTypeNum())
                .or()
                .eq(PlcDeviceDB::getDeviceType, PlcDeviceType.TRANS_PLANTER.getTypeNum())
                .or()
                .eq(PlcDeviceDB::getDeviceType, PlcDeviceType.AUTO_TRAVERSING.getTypeNum())
                .or()
                .eq(PlcDeviceDB::getDeviceType, PlcDeviceType.AUTO_HOIST.getTypeNum());
        List<PlcDeviceDB> plcDeviceDBS = plcdevicedbServiceImpl.list(queryWrapper);
        StationOper stationOper;
        MonomerConveyorOper monomerConveyorOper;
        ToothHoistOper toothHoistOper;
        TransPlanter transPlanter;
        AutoTraversingOper autoTraversingOper;
        AutoHoistOper autoHoistOper;
        if (plcDeviceDBS != null && plcDeviceDBS.size() > 0) {
            for (PlcDeviceDB plcDevice : plcDeviceDBS) {
                Station station = new Station();
                station.setStationName(plcDevice.getDeviceName());
                station.setDeviceLocation(Node.parseGrid(plcDevice.getDeviceLocation()));
                if(plcDevice.getDeviceType()==PlcDeviceType.CHAIN_STATION.getTypeNum()) {
                    stationOper = (StationOper) Plc.deviceBaseNameMap.get(plcDevice.getDeviceName());
                    if (stationOper != null) {
                        station.setCanGet(stationOper.isCanGet() ? "可取" : "不可取");
                        station.setCanPut(stationOper.isCanPut() ? "可放" : "不可放");
                        station.setPalletExist(stationOper.isPalletExist() ? "有货" : "无货");
                        station.setIsError(stationOper.isError() ? "故障" : "未故障");
                        station.setPalletNo(stationOper.getPalletNo());
                        station.setRunIng(stationOper.isRunIng() ? "运行" : "未运行");
                        station.setStationNo(String.valueOf(stationOper.getDeviceNo()));
                        station.setDeviceLocation(Node.parseGrid(plcDevice.getDeviceLocation()));
                    }
                }
                else if(plcDevice.getDeviceType()==PlcDeviceType.MONOMER_CONVEYOR.getTypeNum()){
                    monomerConveyorOper = (MonomerConveyorOper) Plc.deviceBaseNameMap.get(plcDevice.getDeviceName());
                    if (monomerConveyorOper != null) {
//                        station.setCanGet(monomerConveyorOper.isCanGet() ? "可取" : "不可取");
//                        station.setCanPut(stationOper.isCanPut() ? "可放" : "不可放");
                        station.setPalletExist(monomerConveyorOper.hasCargo() ? "有货" : "无货");
                        station.setIsError(monomerConveyorOper.isError() ? "故障" : "未故障");
//                        station.setPalletNo(monomerConveyorOper.getPalletNo());
                        station.setRunIng(monomerConveyorOper.isRunning() ? "运行" : "未运行");
                        station.setStationNo(String.valueOf(monomerConveyorOper.getDeviceNo()));
                        station.setDeviceLocation(Node.parseGrid(plcDevice.getDeviceLocation()));
                    }
                }
                else if(plcDevice.getDeviceType()==PlcDeviceType.TRANS_PLANTER.getTypeNum()){
                    transPlanter = (TransPlanter) Plc.deviceBaseNameMap.get(plcDevice.getDeviceName());
                    if (transPlanter != null) {
//                        station.setCanGet(monomerConveyorOper.isCanGet() ? "可取" : "不可取");
//                        station.setCanPut(stationOper.isCanPut() ? "可放" : "不可放");
                        station.setPalletExist(transPlanter.hasCargo() ? "有货" : "无货");
                        station.setIsError(transPlanter.isErrorState() ? "故障" : "未故障");
//                        station.setPalletNo(monomerConveyorOper.getPalletNo());
                        station.setRunIng(transPlanter.isRunning() ? "运行" : "未运行");
                        station.setStationNo(String.valueOf(transPlanter.getDeviceNo()));
                        station.setDeviceLocation(Node.parseGrid(plcDevice.getDeviceLocation()));
                    }
                }
                else if(plcDevice.getDeviceType()==PlcDeviceType.TOOTH_HOIST.getTypeNum()){
                    toothHoistOper = (ToothHoistOper) Plc.deviceBaseNameMap.get(plcDevice.getDeviceName());
                    if (toothHoistOper != null) {
//                        station.setCanGet(monomerConveyorOper.isCanGet() ? "可取" : "不可取");
//                        station.setCanPut(stationOper.isCanPut() ? "可放" : "不可放");
                        station.setPalletExist(toothHoistOper.hasCargo() ? "有货" : "无货");
                        station.setIsError(toothHoistOper.isErrorState() ? "故障" : "未故障");
//                        station.setPalletNo(monomerConveyorOper.getPalletNo());
                        station.setRunIng(toothHoistOper.isDeviceState() ? "运行" : "未运行");
                        station.setStationNo(String.valueOf(toothHoistOper.getDeviceNo()));
                        station.setDeviceLocation(Node.parseGrid(plcDevice.getDeviceLocation()));
                    }
                }
                else if(plcDevice.getDeviceType()==PlcDeviceType.AUTO_HOIST.getTypeNum()){
                    autoHoistOper = (AutoHoistOper) Plc.deviceBaseNameMap.get(plcDevice.getDeviceName());
                    if (autoHoistOper != null) {
//                        station.setCanGet(monomerConveyorOper.isCanGet() ? "可取" : "不可取");
//                        station.setCanPut(stationOper.isCanPut() ? "可放" : "不可放");
                        station.setPalletExist(autoHoistOper.hasCargo() ? "有货" : "无货");
                        station.setIsError(autoHoistOper.isErrorState() ? "故障" : "未故障");
//                        station.setPalletNo(monomerConveyorOper.getPalletNo());
                        station.setRunIng(autoHoistOper.isDeviceState() ? "运行" : "未运行");
                        station.setStationNo(String.valueOf(autoHoistOper.getDeviceNo()));
                        station.setDeviceLocation(Node.parseGrid(plcDevice.getDeviceLocation()));
                    }
                }
                else if(plcDevice.getDeviceType()==PlcDeviceType.AUTO_TRAVERSING.getTypeNum()){
                    autoTraversingOper = (AutoTraversingOper) Plc.deviceBaseNameMap.get(plcDevice.getDeviceName());
                    if (autoTraversingOper != null) {
//                        station.setCanGet(monomerConveyorOper.isCanGet() ? "可取" : "不可取");
//                        station.setCanPut(stationOper.isCanPut() ? "可放" : "不可放");
                        station.setPalletExist(autoTraversingOper.hasCargo() ? "有货" : "无货");
                        station.setIsError(autoTraversingOper.isError() ? "故障" : "未故障");
//                        station.setPalletNo(monomerConveyorOper.getPalletNo());
                        station.setRunIng(autoTraversingOper.isRunning() ? "运行" : "未运行");
                        station.setStationNo(String.valueOf(autoTraversingOper.getDeviceNo()));
                        station.setDeviceLocation(Node.parseGrid(plcDevice.getDeviceLocation()));
                    }
                }
                stations.add(station);
            }
        } else {
            stations = null;
        }
        return stations;
    }
}
